💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    테이블 정규화(기초) | ✅저자: 이유정(박사)

    🔹 예시 상황: 학생 성적 관리 시스템 만들기 초기에는 아래와 같은 단순한 모델을 만들었다고 가정합니다:

    💬 "하나의 테이블에 모든 정보를 다 넣는 형태"
    학번 이름 학과 과목1 성적1 과목2 성적2
    1 철수 컴퓨터공학 수학 90 영어 85

    Step 1: 제1정규형(1NF) – 원자값만 허용 모든 칼럼은 더 이상 나눌 수 없는 값(원자값)만 포함해야 함.

    개선 전:

    • 과목1/성적1, 과목2/성적2 → 반복되는 그룹
    • 과목이 늘어나면 열이 계속 생겨야 함 ❌
    개선 후 (1NF 적용):
    학번 이름 학과 과목명 성적
    1 철수 컴퓨터공학 수학 90
    1 철수 컴퓨터공학 영어 85
    → 더 이상 반복 컬럼이 없음.
    → 하지만 이름과 학과가 계속 중복됨. (아직 2NF는 아님)

    Step 2: 제2정규형(2NF) – 부분 종속 제거

    • 기본키가 복합키(학번+과목명)인 경우,
    • 학과, 이름이 과목명과는 무관하게 부분 종속됨 → 분리 필요

    개선 후 (2NF 적용) → 테이블 분리

    Student 테이블
    학번 이름 학과
    1 철수 컴퓨터공학
    Score 테이블
    학번 과목명 성적
    1 수학 90
    1 영어 85
    → 이름/학과는 학번만 알면 알 수 있음
    Score 테이블은 학번과 과목명으로만 구성됨

    Step 3: 제3정규형(3NF) – 이행 종속 제거 기본키 이외의 컬럼이 또 다른 컬럼에 종속되는 경우 제거

    예: 학과학과 이름을 따로 관리한다면? 개선 후 (3NF 적용) → 학과 정보 테이블 분리

    Department 테이블
    학과코드 학과명
    CSE 컴퓨터공학
    Student 테이블
    학번 이름 학과코드
    1 철수 CSE
    Score 테이블 (변화 없음)
    학번 과목명 성적
    1 수학 90
    1 영어 85

    ✅ 최종 Django 모델 코드 예시

    # models.py
    
    from django.db import models
    
    class Department(models.Model):
        code = models.CharField(max_length=10, primary_key=True)
        name = models.CharField(max_length=100)
    
        def __str__(self):
            return self.name
    
    class Student(models.Model):
        student_id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=100)
        department = models.ForeignKey(Department, on_delete=models.CASCADE)
    
        def __str__(self):
            return self.name
    
    class Score(models.Model):
        student = models.ForeignKey(Student, on_delete=models.CASCADE)
        subject = models.CharField(max_length=100)
        grade = models.IntegerField()
    
        def __str__(self):
            return f"{self.student.name} - {self.subject}: {self.grade}"
    
    TOP
    preload preload